package com.zx.onlineeducation.common.servicebase.handler;

import com.zx.onlineeducation.common.servicebase.exception.OnlineEducationException;
import com.zx.onlineeducation.common.util.ExceptionUtil;
import com.zx.onlineeducation.common.util.R;
import com.zx.onlineeducation.common.util.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;

/**
 * 统一异常处理器
 *
 * @author 郑雪
 * @since 2022-01-08
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 全局异常处理方法
     *
     * @return com.zx.onlineeducation.common.util.R
     * @param exception 异常对象
     * @author 郑雪
     * @since 2022-01-08
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R error(Exception exception) {
        exception.printStackTrace();
        this.log(exception);
        return R.error();
    }

    /**
     * 特定异常处理方法，空指针异常
     *
     * @return com.zx.onlineeducation.common.util.R
     * @param exception 空指针异常对象
     * @author 郑雪
     * @since 2022-01-08
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public R error(NullPointerException exception) {
        exception.printStackTrace();
        this.log(exception);
        return R.resultCode(ResultCodeEnum.NULL_POINT);
    }

    /**
     * 特定异常处理方法：客户端连接异常
     *
     * @return com.zx.onlineeducation.common.util.R
     * @param exception 客户端连接异常对象
     * @author 郑雪
     * @since 2022-01-08
     */
    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseBody
    public R error(HttpClientErrorException exception) {
        exception.printStackTrace();
        this.log(exception);
        return R.resultCode(ResultCodeEnum.HTTP_CLIENT_ERROR);
    }

    /**
     * 自定义异常处理方法：在线教育项目异常
     *
     * @return com.zx.onlineeducation.common.util.R
     * @param exception 在线教育项目异常对象
     * @author 郑雪
     * @since 2022-01-08
     */
    @ExceptionHandler(OnlineEducationException.class)
    @ResponseBody
    public R error(OnlineEducationException exception) {
        exception.printStackTrace();
        this.log(exception);
        Integer code = exception.getCode();
        String message = exception.getMessage();
        R r = R.error();
        if (code != null) {
            r.code(code);
        }
        if (!StringUtils.isEmpty(message)) {
            r.message(message);
        }
        return r;
    }

    /**
     * 通用的打印异常日志方法
     *
     * @param exception 异常对象
     * @author 郑雪
     * @since 2022-01-08
     */
    private void log(Exception exception) {
        StackTraceElement stackTraceElement = exception.getStackTrace()[0];
        log.error("异常类名：{}", exception.getClass());
        log.error("异常消息：{}", exception.getMessage());
        log.error("异常详情 -> 出错的类：{}，出错的行数：{}，出错的方法：{}",
                stackTraceElement.getClassName(),
                stackTraceElement.getLineNumber(),
                stackTraceElement.getMethodName());
        log.error(ExceptionUtil.getMessage(exception));
    }
}
